package qc.module.platform.api.controller;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import qc.common.core.constants.QCAuthConstant;
import qc.common.core.exception.QCPromptException;
import qc.common.core.exception.QcTokenInvalidException;
import qc.common.core.tree.QCTreeNode;
import qc.module.platform.dto.dept.DeptDto;
import qc.module.platform.dto.dept.DeptSimpleDto;
import qc.module.platform.dto.param.group.ParamGroupDto;
import qc.module.platform.dto.param.value.ObjectParamValuesDto;
import qc.module.platform.dto.param.value.ParamValuesGetConditionDto;
import qc.module.platform.dto.project.ProjectParamValueConditionDto;
import qc.module.platform.dto.uac.UacUserInfoDto;
import qc.module.platform.dto.user.UserQueryConditionDto;
import qc.module.platform.dto.user.UserSimpleInfoDto;
import qc.module.platform.entity.QcDepts;
import qc.module.platform.entity.QcUserloginLogs;
import qc.module.platform.mapper.DeptMapper;
import qc.module.platform.service.*;

import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Platform中统一提供给外部调用接口Controller
 *
 * @author QuCheng Tech
 * @since 2025/3/3
 */
@RestController
@RequestMapping("/invoke")
public class InvokeController {
    private UserAccessControlService uacService;
    private DeptService deptService;
    private UserLoginLogService userLoginLogService;
    private DeptUserService deptUserService;
    private UserService userService;
    private ParamService paramService;
    private ParamValueService paramValueService;

    @Autowired
    public void setUserAccessControlService(UserAccessControlService service) {
        this.uacService = service;
    }

    @Autowired
    public void setDeptService(DeptService deptService) {
        this.deptService = deptService;
    }

    @Autowired
    public void setUserLoginLogService(UserLoginLogService userLoginLogService) {
        this.userLoginLogService = userLoginLogService;
    }

    @Autowired
    public void setDeptUserService(DeptUserService deptUserService) {
        this.deptUserService = deptUserService;
    }

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Autowired
    public void setParamService(ParamService paramService) {
        this.paramService = paramService;
    }

    @Autowired
    public void setParamValueService(ParamValueService paramValueService) {
        this.paramValueService = paramValueService;
    }

    @Autowired
    HttpServletRequest request;

    /**
     * 获取当前登录用户信息接口：项目编码和token均从headers中获取
     *
     * @return 用户信息，包含ID、名称、手机号、项目编码
     * @author QuCheng Tech
     * @since 2023/5/28
     */
    @GetMapping("/userinfo")
    public UacUserInfoDto getUserInfo() throws QcTokenInvalidException {
        //权限验证需要token，获取token
        String token = request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY);
        //如果在请求头中指定了当前项目编码，获取用户信息时固定使用该项目编码
        String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);

        return uacService.getUacUserInfoByToken(token, projectCode);
    }

    //获取用户集合接口：1.获取项目中的用户、2.获取项目中指定根部门ID的用户（同一个项目中按部门分项目，包含指定的根部门和所有子级部门中的用户）

    /**
     * 1.获取当前用户所在项目中的用户信息集合；项目编码从headers中获取
     *
     * @return 用户简要信息集合
     * @author QcCheng Tech
     * @since 2023/2/8
     */
    @RequestMapping(value = "/projectusers", method = {RequestMethod.GET, RequestMethod.POST})
    public List<UserSimpleInfoDto> getProjectUserSimpleInfoList() throws QCPromptException {
        //从headers中获取项目编码
        String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);
        if (StringUtils.isBlank(projectCode))
            throw new QCPromptException("获取项目中的用户信息集合时项目编码不能为空");

        UserQueryConditionDto condition = new UserQueryConditionDto();
        condition.setProject(projectCode);

        return userService.queryProjectUserSimple(condition);
    }

    /***
     * 2.获取指定部门ID及子级部门的用户信息集合；项目编码从header中获取，如果获取不到项目编码则不根据项目编码过滤
     *
     * @param id 指定的部门ID
     * @return java.util.List<qc.module.platform.dto.user.UserSimpleInfoDto>
     * @author QuCheng Tech
     * @since 2025/3/3
     */
    @RequestMapping(value = "/deptchildusers", method = {RequestMethod.GET, RequestMethod.POST})
    public List<UserSimpleInfoDto> getProjectDeptChildUserSimpleInfoListByParam(@RequestParam(value = "id", required = true) int id) throws QCPromptException {
        return getProjectDeptChildUserSimpleInfoList(id);
    }

    /***
     * 2.获取指定部门ID及子级部门的用户信息集合；项目编码从header中获取，如果获取不到项目编码则不根据项目编码过滤
     *
     * @param id 指定的部门ID
     * @return java.util.List<qc.module.platform.dto.user.UserSimpleInfoDto>
     * @author QuCheng Tech
     * @since 2025/3/3
     */
    @RequestMapping(value = "/deptchildusers/{id}", method = {RequestMethod.GET, RequestMethod.POST})
    public List<UserSimpleInfoDto> getProjectDeptChildUserSimpleInfoListByPath(@PathVariable(value = "id", required = true) int id) throws QCPromptException {
        return getProjectDeptChildUserSimpleInfoList(id);
    }

    /***
     * 获取指定部门ID及子级部门的用户信息集合；项目编码从header中获取，如果获取不到项目编码则不根据项目编码过滤
     *
     * @param deptId 指定的部门ID
     * @return java.util.List<qc.module.platform.dto.user.UserSimpleInfoDto>
     * @author QuCheng Tech
     * @since 2025/3/3
     */
    List<UserSimpleInfoDto> getProjectDeptChildUserSimpleInfoList(int deptId) throws QCPromptException {
        if (deptId < 0x1)
            throw new QCPromptException("获取指定部门及子级部门的用户信息集合时指定的部门ID无效");

        //先获取指定部门的信息
        //获取项目中的所有部门集合和用户集合
        //得到部门及子级部门的ID集合，在项目所有用户集合中进行过滤
        DeptDto dept = deptService.get(deptId);
        if (dept == null)
            throw new QCPromptException("获取指定部门及子级部门的用户信息集合时指定的部门信息不存在");
        //获取部门中的项目编码
        String projectCode = dept.getPcode();
        //获取项目中的所有部门
        List<QcDepts> projectAllDepts = deptService.getProjectAllDepts(projectCode, true);
        if (projectAllDepts != null && projectAllDepts.size() > 0x0) {
            //获取指定的部门及子级部门ID集合
            List<Integer> deptChildsIds = deptService.getDeptChildsSimpleInfoList(deptId, projectAllDepts);
            if (deptChildsIds != null && deptChildsIds.size() > 0x0) {
                //获取部门ID集合关联的用户ID集合
                List<Integer> getDeptsRelatedUserIds = deptUserService.getDeptsRelatedUserIds(deptChildsIds);
                if (getDeptsRelatedUserIds != null && getDeptsRelatedUserIds.size() > 0x0) {
                    //获取项目中的所有用户
                    UserQueryConditionDto condition = new UserQueryConditionDto();
                    condition.setProject(projectCode);

                    List<UserSimpleInfoDto> projectAllUsers = userService.queryProjectUserSimple(condition);
                    if (projectAllUsers != null && projectAllUsers.size() > 0x0) {
                        List<UserSimpleInfoDto> result = new ArrayList<>();

                        for (UserSimpleInfoDto user : projectAllUsers) {
                            List<Integer> filterByUserId = getDeptsRelatedUserIds.stream().filter(p -> p.intValue() == user.getId()).collect(Collectors.toList());
                            if (filterByUserId != null && filterByUserId.size() > 0x0)
                                result.add(user);
                        }
                        return result;
                    }
                }
            }
        }

        return null;
    }

    /**
     * 获取指定用户ID作为负责人的部门ID集合接口：项目编码可以由headers中传入获取
     *
     * @param id 指定的用户ID
     * @return List<Integer> 部门ID集合
     * @author QuCheng Tech
     * @since 2024/11/1
     */
    @GetMapping("/leaderdeptids")
    public List<Integer> getUserIsLeaderDeptIdsByParam(@RequestParam(value = "id", required = true) int id) throws QCPromptException {
        //项目编码从headers中获取，如果获取不到根据token从用户登录信息中获取
        String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);

        return getUserIsLeaderDeptIds(id, projectCode);
    }

    /**
     * 获取指定用户ID作为负责人的部门ID集合接口：项目编码可以由headers中传入获取
     *
     * @param id 指定的用户ID
     * @return List<Integer> 部门ID集合
     * @author QuCheng Tech
     * @since 2024/11/1
     */
    @GetMapping("/leaderdeptids/{id}")
    public List<Integer> getUserIsLeaderDeptIdsByPath(@PathVariable(value = "id", required = true) int id) throws QCPromptException {
        //项目编码从headers中获取，如果获取不到根据token从用户登录信息中获取
        String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);

        return getUserIsLeaderDeptIds(id, projectCode);
    }

    /**
     * 获取指定用户ID作为负责人的部门ID集合接口；用户ID必须指定，项目编码可以为空
     *
     * @param userId 用户ID，必须指定
     * @param projectCode 项目编码，可以为空
     * @return java.util.List<java.lang.Integer>
     * @author QuCheng Tech
     * @since 2025/3/3
     */
    List<Integer> getUserIsLeaderDeptIds(int userId, String projectCode) throws QCPromptException {
        //项目编码可以为空
        //if (StringUtils.isBlank(projectCode))
        //    throw new QCPromptException("获取用户作为负责人的部门ID集合时项目编码不能为空");

        return deptUserService.getUserIsLeaderDeptIds(userId, projectCode);
    }

    //获取部门接口：
    //1.获取当前用户关联的部门List(获取用户直接关联的部门集合，不包含关联部门的下级和子级部门)：用户和项目编码均从header中获取
    //2.获取当前用户有访问权限的部门List(获取用户直接关联的部门集合，包含关联部门的下级和子级部门)；用户和项目编码均从header中获取
    //3.获取指定项目中的根部门List；项目编码从headers中获取
    //4.获取指定项目中的所有部门List；通过参数指定项目编码；返回的部门信息中包含部门层级序号，用于调用方需要设置数据权限控制的部门列表时使用
    //5.获取指定部门及子级部门List：通过参数指定部门ID
    //6.获取指定部门及子级部门Tree；通过参数指定部门ID

    /**
     * 获取当前用户关联的部门ID集合（获取用户直接关联的部门ID集合，不包含关联部门的下级和子级部门）；用户和项目编码均从header中获取
     *
     * @return java.util.List<java.lang.Integer>
     * @author QuCheng Tech
     * @since 2025/3/4
     */
    @GetMapping("/userrelatedeptids")
    public List<Integer> getUserRelatedDeptIds() throws QCPromptException, QcTokenInvalidException {
        //根据token获取用户信息，此处接口为根据用户获取所在部门信息，必须指定用户ID
        int userId = 0x0;
        //项目编码的获取：先从传入参数中获取，如果为空再请求头中获取、如果为空再根据token在登录日志中获取
        String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);

        String token = request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY);
        //根据token获取到有效用户信息
        QcUserloginLogs loginLog = userLoginLogService.getUserLoginLogByToken(token, true);
        if (loginLog == null)
            throw new QCPromptException("获取用户关联的部门集合时根据token获取不到有效用户信息");

        userId = loginLog.getUid();
        //如果传入id参数中未指定项目编码，从token中获取到的用户信息中获取项目编码
        //如果传入参数中项目编码为空，从请求头中获取当前项目编码
        if (StringUtils.isBlank(projectCode))
            projectCode = loginLog.getProject();

        if (StringUtils.isBlank(projectCode))
            throw new QCPromptException("获取用户关联的部门集合时项目编码不能为空");

        if (userId < 0x1)
            throw new QCPromptException("获取用户关联的部门集合时用户ID无效");

        return deptUserService.getUserRelatedDeptIds(userId, projectCode);
    }

    /**
     * 1.获取当前用户关联的部门List(获取用户直接关联的部门集合，不包含关联部门的下级和子级部门)：用户和项目编码均从header中获取
     *
     * @return java.util.List<qc.module.platform.dto.dept.DeptSimpleDto>
     * @author QuCheng Tech
     * @since 2025/3/3
     */
    @GetMapping("/userrelatedeptlist")
    public List<DeptSimpleDto> getUserRelatedDeptList() throws QCPromptException, QcTokenInvalidException {
        //根据token获取用户信息，此处接口为根据用户获取所在部门信息，必须指定用户ID
        int userId = 0x0;
        //项目编码的获取：先从传入参数中获取，如果为空再请求头中获取、如果为空再根据token在登录日志中获取
        String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);

        String token = request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY);
        //根据token获取到有效用户信息
        QcUserloginLogs loginLog = userLoginLogService.getUserLoginLogByToken(token, true);
        if (loginLog == null)
            throw new QCPromptException("获取用户关联的部门集合时根据token获取不到有效用户信息");

        userId = loginLog.getUid();
        //如果传入id参数中未指定项目编码，从token中获取到的用户信息中获取项目编码
        //如果传入参数中项目编码为空，从请求头中获取当前项目编码
        if (StringUtils.isBlank(projectCode))
            projectCode = loginLog.getProject();

        if (StringUtils.isBlank(projectCode))
            throw new QCPromptException("获取用户关联的部门集合时项目编码不能为空");

        if (userId < 0x1)
            throw new QCPromptException("获取用户关联的部门集合时用户ID无效");

        return deptService.querySimpleInfoList(projectCode, false, userId, false);
    }

    /**
     * 获取当前用户能访问的部门ID集合
     *
     * @return java.util.List<java.lang.Integer>
     * @author QuCheng Tech
     * @since 2025/3/3
     */
    @GetMapping("/usercanaccessdeptids")
    public List<Integer> getUserCanAccessDeptIds() throws QCPromptException, QcTokenInvalidException {
        //根据token获取用户信息，此处接口为根据用户获取所在部门信息，必须指定用户ID
        int userId = 0x0;
        //项目编码的获取：先从传入参数中获取，如果为空再请求头中获取、如果为空再根据token在登录日志中获取
        String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);

        String token = request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY);
        //根据token获取到有效用户信息
        QcUserloginLogs loginLog = userLoginLogService.getUserLoginLogByToken(token, true);
        if (loginLog == null)
            throw new QCPromptException("获取用户关联的部门集合时根据token获取不到有效用户信息");

        userId = loginLog.getUid();
        //如果传入id参数中未指定项目编码，从token中获取到的用户信息中获取项目编码
        //如果传入参数中项目编码为空，从请求头中获取当前项目编码
        if (StringUtils.isBlank(projectCode))
            projectCode = loginLog.getProject();

        if (StringUtils.isBlank(projectCode))
            throw new QCPromptException("获取用户关联的部门集合时项目编码不能为空");

        if (userId < 0x1)
            throw new QCPromptException("获取用户关联的部门集合时用户ID无效");

        //先根据项目获取项目中所有的部门集合，再获取用户在项目中的关联部门ID集合，遍历关联部门ID集合获取子级部门信息；
        //获取项目中的所有部门
        List<QcDepts> projectAllDepts = deptService.getProjectAllDepts(projectCode, true);
        if (projectAllDepts != null && projectAllDepts.size() > 0x0) {
            //获取用户在项目中关联的部门ID集合
            List<Integer> getUserRelatedDeptIds = deptUserService.getUserRelatedDeptIds(userId, projectCode);
            if (getUserRelatedDeptIds != null && getUserRelatedDeptIds.size() > 0x0) {
                //获取有访问权限的所有部门ID，根据直接关联的部门获取子级
                return deptService.getCanAccessDeptIds(getUserRelatedDeptIds, projectAllDepts);
            }
        }

        return null;
    }

    /**
     * 2.获取当前用户有访问权限的部门List(获取用户直接关联的部门集合，包含关联部门的下级和子级部门)；用户和项目编码均从header中获取
     *
     * @return java.util.List<qc.module.platform.dto.dept.DeptSimpleDto>
     * @author QuCheng Tech
     * @since 2025/3/3
     */
    @GetMapping("/useraccessdeptlist")
    public List<DeptSimpleDto> getUserCanAccessDeptList() throws QCPromptException, QcTokenInvalidException {
        //根据token获取用户信息，此处接口为根据用户获取所在部门信息，必须指定用户ID
        int userId = 0x0;
        //项目编码的获取：先从传入参数中获取，如果为空再请求头中获取、如果为空再根据token在登录日志中获取
        String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);

        String token = request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY);
        //根据token获取到有效用户信息
        QcUserloginLogs loginLog = userLoginLogService.getUserLoginLogByToken(token, true);
        if (loginLog == null)
            throw new QCPromptException("获取用户有访问权限的部门集合时根据token获取不到有效用户信息");

        userId = loginLog.getUid();
        //如果传入id参数中未指定项目编码，从token中获取到的用户信息中获取项目编码
        //如果传入参数中项目编码为空，从请求头中获取当前项目编码
        if (StringUtils.isBlank(projectCode))
            projectCode = loginLog.getProject();

        if (StringUtils.isBlank(projectCode))
            throw new QCPromptException("获取用户有访问权限的部门集合时项目编码不能为空");

        if (userId < 0x1)
            throw new QCPromptException("获取用户有访问权限的部门集合时用户ID无效");

        //先根据项目获取项目中所有的部门集合，再获取用户在项目中的关联部门ID集合，遍历关联部门ID集合获取子级部门信息；
        //获取项目中的所有部门
        List<QcDepts> projectAllDepts = deptService.getProjectAllDepts(projectCode, true);
        if (projectAllDepts != null && projectAllDepts.size() > 0x0) {
            //获取用户在项目中关联的部门ID集合
            List<Integer> getUserRelatedDeptIds = deptUserService.getUserRelatedDeptIds(userId, projectCode);
            if (getUserRelatedDeptIds != null && getUserRelatedDeptIds.size() > 0x0) {
                //获取有访问权限的所有部门ID，根据直接关联的部门获取子级
                List<Integer> getCanAccessDeptIds = deptService.getCanAccessDeptIds(getUserRelatedDeptIds, projectAllDepts);
                if (getCanAccessDeptIds != null && getCanAccessDeptIds.size() > 0x0) {
                    //从所有部门集合中进行筛选
                    List<DeptSimpleDto> result = new ArrayList<>();
                    for (int id : getCanAccessDeptIds) {
                        Optional<QcDepts> filterByDeptId = projectAllDepts.stream().filter(p -> p.getId().intValue() == id).findFirst();
                        if (filterByDeptId != null && filterByDeptId.isPresent())
                            result.add(DeptMapper.MAPPER.toSimpleDto(DeptMapper.MAPPER.toDto(filterByDeptId.get())));
                    }

                    return result;
                }
            }
        }

        return null;
    }

    /**
     * 3.获取指定项目中的根部门List；项目编码从headers中获取
     *
     * @return java.util.List<qc.module.platform.dto.dept.DeptSimpleDto>
     * @author QuCheng Tech
     * @since 2025/3/3
     */
    @GetMapping("/projectrootdeptlist")
    public List<DeptSimpleDto> getProjectValidRootDepts() throws QCPromptException, QcTokenInvalidException {
        //项目编码的获取：先从请求头中获取、如果为空再根据token在登录日志中获取
        String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);
        //判断是否有token，如果有token根据token获取对应用户在项目中所关联的部门ID集合，后续查询部门信息只再关联的部门中查找
        Integer[] userDeptIds = null;
        //根据token获取项目编码
        String token = request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY);
        if (StringUtils.isNotBlank(token)) {
            //从uac中根据token获取项目编码
            QcUserloginLogs loginLog = userLoginLogService.getUserLoginLogByToken(token, true);
            //如果传入参数中项目编码为空，从请求头中获取当前项目编码
            if (StringUtils.isBlank(projectCode)) {
                if (StringUtils.isBlank(loginLog.getProject()))
                    throw new QCPromptException("根据token获取到的用户信息中无项目编码信息");

                projectCode = loginLog.getProject();
            }
            //获取用户在指定项目中关联的部门
            List<Integer> deptIds = deptUserService.getUserRelatedDeptIds(loginLog.getUid(), projectCode);
            //如果用户关联的部门为空，无法继续获取根部门信息
            if (deptIds == null || deptIds.size() < 0x1)
                return null;
            else
                userDeptIds = deptIds.stream().map(p -> p.intValue()).toArray(Integer[]::new);
        }

        //判断必须要有项目编码
        if (StringUtils.isBlank(projectCode))
            throw new QCPromptException("根据token获取到的用户信息中无项目编码信息");

        //查询指定项目编码中的所有有效部门，在有效部门集合中进行筛选
        List<QcDepts> projectDepts = deptService.getProjectAllDepts(projectCode, true);
        if (projectDepts != null && projectDepts.size() > 0x0) {
            //筛选出根节点部门
            List<QcDepts> projectRootDepts = projectDepts.stream().filter(p -> p.getParentid() == null || p.getParentid().intValue() < 0x1).collect(Collectors.toList());
            if (projectRootDepts != null && projectRootDepts.size() > 0x0) {
                //如果没有指定用户所属部门集合，返回全部根部门集合；如果指定了用户所属部门集合，在集合中进行筛选
                if (userDeptIds == null || userDeptIds.length < 0x1)
                    return DeptMapper.MAPPER.toSimpleDtoList(DeptMapper.MAPPER.toDtoList(projectRootDepts));
                else {
                    List<DeptSimpleDto> result = new ArrayList<>();

                    for (Integer userDeptId : userDeptIds) {
                        List<QcDepts> filterByDeptId = projectDepts.stream().filter(p -> p.getId().intValue() == userDeptId.intValue()).collect(Collectors.toList());
                        if (filterByDeptId != null && filterByDeptId.size() > 0x0) {
                            QcDepts dept = filterByDeptId.get(0x0);
                            while (dept != null && dept.getParentid() != null && dept.getParentid().intValue() > 0x0) {
                                //部门信息不为空并且父级ID不为空，继续获取父级信息
                                QcDepts finalDept = dept;
                                List<QcDepts> parentDepts = projectDepts.stream().filter(p -> p.getId().intValue() == finalDept.getParentid().intValue()).collect(Collectors.toList());
                                //如果得不到父级，跳出循环，继续用户所属部门ID集合中的下一个
                                if (parentDepts != null && parentDepts.size() > 0x0)
                                    dept = parentDepts.get(0x0);
                                else
                                    break;
                            }
                            //如果最终得到的父级部门信息不为空，返回该部门信息作为根部门
                            if (dept != null) {
                                result.add(DeptMapper.MAPPER.toSimpleDto(DeptMapper.MAPPER.toDto(dept)));
                            }
                        }
                    }

                    return result;
                }
            }
        }

        return null;
    }

    /**
     * 4.获取指定项目中的所有部门List；通过参数指定项目编码；返回的部门信息中包含部门层级序号，用于调用方需要设置数据权限控制的部门列表时使用
     *
     * @param id 指定的项目编码，必须传入
     * @return java.util.List<qc.module.platform.dto.dept.DeptSimpleDto>
     * @author QuCheng Tech
     * @since 2025/3/4
     */
    @GetMapping("/projectdeptlist")
    public List<DeptSimpleDto> getProjectDeptListByParam(@RequestParam(name = "id", required = true) String id) throws QCPromptException {
        return deptService.querySimpleInfoList(id, false, 0x0, false);
    }

    /**
     * 4.获取指定项目中的所有部门List；通过参数指定项目编码；返回的部门信息中包含部门层级序号，用于调用方需要设置数据权限控制的部门列表时使用
     *
     * @param id 指定的项目编码，必须传入
     * @return java.util.List<qc.module.platform.dto.dept.DeptSimpleDto>
     * @author QuCheng Tech
     * @since 2025/3/4
     */
    @GetMapping("/projectdeptlist/{id}")
    public List<DeptSimpleDto> getProjectDeptListByPath(@PathVariable(name = "id", required = true) String id) throws QCPromptException {
        return deptService.querySimpleInfoList(id, false, 0x0, false);
    }

    /**
     * 5.获取指定部门及子级部门List：通过参数指定部门ID
     * <p>
     * 获取指定部门ID下的所有部门集合，包含自己和所有子级；返回List，使用level和parentid标识层级关系；
     *
     * @param id 部门ID
     * @return List<DeptSimpleDto>
     * @author QuCheng Tech
     * @since 2024/11/21
     */
    @GetMapping("/deptchildslist")
    public List<DeptSimpleDto> getDeptChildsListByParam(@RequestParam(name = "id", required = true) int id) {
        return deptService.getDeptChildsList(id);
    }

    /**
     * 5.获取指定部门及子级部门List：通过参数指定部门ID
     * <p>
     * 获取指定部门ID下的所有部门集合，包含自己和所有子级；返回List，使用level和parentid标识层级关系；
     *
     * @param id 部门ID
     * @return List<DeptSimpleDto>
     * @author QuCheng Tech
     * @since 2024/11/21
     */
    @GetMapping("/deptchildslist/{id}")
    public List<DeptSimpleDto> getDeptChildsListByPath(@PathVariable(name = "id", required = true) int id) {
        return deptService.getDeptChildsList(id);
    }

    /**
     * 6.获取指定部门及子级部门Tree；通过参数指定部门ID
     * <p>
     * 获取指定部门ID下的所有部门集合，包含自己和所有子级；返回树形结构
     *
     * @param id 部门ID
     * @return List<QCTreeNode>
     * @author QuCheng Tech
     * @since 2024/11/21
     */
    @GetMapping("/deptchildstree")
    public List<QCTreeNode> getDeptChildsTreeByParam(@RequestParam(name = "id", required = true) int id) {
        return deptService.getDeptChildsTree(id);
    }

    /**
     * 6.获取指定部门及子级部门Tree；通过参数指定部门ID
     * <p>
     * 获取指定部门ID下的所有部门集合，包含自己和所有子级；返回树形结构
     *
     * @param id 部门ID
     * @return List<QCTreeNode>
     * @author QuCheng Tech
     * @since 2024/11/21
     */
    @GetMapping("/deptchildstree/{id}")
    public List<QCTreeNode> getDeptChildsTreeByPath(@PathVariable(name = "id", required = true) int id) {
        return deptService.getDeptChildsTree(id);
    }

    /**
     * 获取指定参数值
     * 传入条件：数据库表名称、对象ID/编码、参数名称。3个条件均必须传入，数据库表名称为1个，对象ID/编码可以为1个或多个，参数名称可以为1个或多个（支持上下级节点选择）。
     *
     * @param
     * @return
     * @author QuCheng Tech
     * @since 2025/4/16
     */
    @RequestMapping(value = "/params", method = {RequestMethod.POST, RequestMethod.GET})
    public List<ObjectParamValuesDto> getParamValues(@RequestBody ParamValuesGetConditionDto condition) throws QCPromptException, SQLException {
        return paramValueService.getValues(condition);
    }

    /**
     * 获取项目参数值
     * 可以指定项目编码，如果未指定项目编码依次从header、根据token进行获取；
     * 参数节点名称可以为1个或多个（支持上下级节点选择）。优先根据参数节点名称进行获取，如果参数节点名称为空则根据参数分组编码获取；
     *
     * @param
     * @return
     * @author QuCheng Tech
     * @since 2025/4/16
     */
    @RequestMapping(value = "/prjparams", method = {RequestMethod.POST, RequestMethod.GET})
    public ObjectParamValuesDto getProjectParamValues(@RequestBody ProjectParamValueConditionDto condition) throws QCPromptException, SQLException, QcTokenInvalidException {
        //判断输入信息和条件
        if (condition == null)
            throw new QCPromptException("获取项目参数信息的条件对象不能为空");
        //项目编码：如果传入中为空，依次从header、根据token获取
        if (StringUtils.isBlank(condition.getProjectcode())) {
            //从headers中获取项目编码
            String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);
            if (StringUtils.isNotBlank(projectCode)) {
                condition.setProjectcode(projectCode);
            } else {
                //如果header中的项目编码为空，根据token获取项目编码
                String token = request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY);
                if (StringUtils.isNotBlank(token)) {
                    //从uac中根据token获取项目编码
                    QcUserloginLogs loginLog = userLoginLogService.getUserLoginLogByToken(token, true);
                    if (loginLog != null && StringUtils.isNotBlank(loginLog.getProject()))
                        condition.setProjectcode(loginLog.getProject());
                }
            }
        }
        if (StringUtils.isBlank(condition.getProjectcode()))
            throw new QCPromptException("获取项目参数信息的项目编码不能为空");

        ParamValuesGetConditionDto getParamValuesCondition = new ParamValuesGetConditionDto();
        //先默认查询项目参数对应的表名为：qc_project
        getParamValuesCondition.setTablecode("qc_project");
        getParamValuesCondition.setObjectids(condition.getProjectcode());
        //查询参数值的节点名称：如果在传入条件中直接指定节点名称则直接使用，如果没有指定则根据分组编码进行获取
        if (StringUtils.isNotBlank(condition.getParamnodes())) {
            getParamValuesCondition.setParamnodes(condition.getParamnodes());
        } else {
            if (StringUtils.isBlank(condition.getGroupcode()))
                throw new QCPromptException("获取项目参数信息的参数分组编码不能为空");

            //从传入的参数分组编码获取参数分组信息，使用参数分组信息中的数据库表编码和节点名称
            ParamGroupDto paramGroup = paramService.getGroup(condition.getGroupcode());
            if (paramGroup == null)
                throw new QCPromptException("获取项目参数信息的参数分组编码获取不到有效的参数分组信息");

            getParamValuesCondition.setTablecode(paramGroup.getTablecode());
            getParamValuesCondition.setParamnodes(paramGroup.getNodes());
        }

        List<ObjectParamValuesDto> paramValues = paramValueService.getValues(getParamValuesCondition);
        //查询指定的1个项目的参数值，因此集合中应该至多有1个，返回结果为参数值集合中的第1个
        if (paramValues != null && paramValues.size() > 0x0)
            return paramValues.get(0x0);

        return null;
    }
}
